using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using dnAnalytics.Math;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.Exceptions;

namespace dnAnalytics.UnitTests.LinearAlgebra
{
    public class DenseMatrixTest : AbstractMatrixTest
    {
        public override Matrix GetMatrix(int order)
        {
            return MatrixBuilder.CreateMatrix(order, MatrixType.Dense);
        }

        public override Matrix GetMatrix(int m, int n)
        {
            return MatrixBuilder.CreateMatrix(m, n, MatrixType.Dense);
        }

        public override Matrix GetMatrix(double[,] data)
        {
            int rows = data.GetLength(0);
            int cols = data.GetLength(1);
            Matrix ret = MatrixBuilder.CreateMatrix(rows, cols, MatrixType.Dense);
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    ret[i, j] = data[i, j];
                }
            }

            return ret;
        }

        public override Vector GetVector(int size)
        {
            return VectorBuilder.CreateVector(size, VectorType.Dense);
        }

        public override Vector GetVector(double[] source)
        {
            return VectorBuilder.CreateVector(source, VectorType.Dense);
        }
    }

    [TestFixture]
    [Category("Managed")]
    [Category("Dense")]
    public class ManagedDenseMatrixTest : DenseMatrixTest
    {
        static ManagedDenseMatrixTest(){
            dnAnalytics.Settings.UseNativeLibrary = false;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Dense;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Dense;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Mkl")]
    [Category("Dense")]
    public class MklDenseMatrixTest : DenseMatrixTest
    {
        static MklDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Mkl;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Mkl;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Dense;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Dense;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Acml")]
    [Category("Dense")]
    public class AcmlDenseMatrixTest : DenseMatrixTest
    {
        static AcmlDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Acml;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Acml;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Dense;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Dense;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Atlas")]
    [Category("Dense")]
    public class AtlasClapackDenseMatrixTest : DenseMatrixTest
    {
        static AtlasClapackDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Atlas;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Clapack;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Dense;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Dense;
        }
    }
    
    [TestFixture]
    [Category("Managed")]
    [Category("Dense")]
    public class ManagedSparseDenseMatrixTest : DenseMatrixTest
    {
        static ManagedSparseDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = false;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Sparse;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Sparse;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Mkl")]
    [Category("Dense")]
    public class MklSparseDenseMatrixTest : DenseMatrixTest
    {
        static MklSparseDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Mkl;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Mkl;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Sparse;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Sparse;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Acml")]
    [Category("Dense")]
    public class AcmlSparseDenseMatrixTest : DenseMatrixTest
    {
        static AcmlSparseDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Acml;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Acml;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Sparse;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Sparse;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("Atlas")]
    [Category("Dense")]
    public class AtlasClapackSparseDenseMatrixTest : DenseMatrixTest
    {
        static AtlasClapackSparseDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Atlas;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.Clapack;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Sparse;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Sparse;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("AcmlIFort")]
    [Category("Dense")]
    public class AcmlIFortDenseMatrixTest : DenseMatrixTest
    {
        static AcmlIFortDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Acml;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.AcmlIFort;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Dense;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Dense;
        }
    }

    [TestFixture]
    [Category("Native")]
    [Category("AcmlIFort")]
    [Category("Dense")]
    public class AcmlIFortSparseDenseMatrixTest : DenseMatrixTest
    {
        static AcmlIFortSparseDenseMatrixTest()
        {
            dnAnalytics.Settings.UseNativeLibrary = true;
            dnAnalytics.Settings.Blas = dnAnalytics.LinearAlgebra.Native.BlasProvider.Acml;
            dnAnalytics.Settings.Lapack = dnAnalytics.LinearAlgebra.Native.LapackProvider.AcmlIFort;
            dnAnalytics.Settings.DefaultMatrixType = MatrixType.Sparse;
            dnAnalytics.Settings.DefaultVectorType = VectorType.Sparse;
        }
    }
}
